两
个
GC
案
例
唯
品
会
基
础
架
构
组
王
伟
Agenda
Case1:
CMS gc
Case2:
堆
外
内
存
OOM(off-heap)
垃
圾
收
集
算
法
•
复
制
算
法
:
新
生
代
(
98%
)
,
G1
Region
之
间
.
效
率
高
.
•
标
记
-
清
除
(
Mark-Sweep
)
算
法
:
CMS
•
标
记
-
整
理
(
Mark-compact
)
算
法
:
G1
整
体
上
来
看
,
CMS -XX
:
UseCMSCompactAtFullCollection
Low Pause gc
vs.
Throughput gc
JVM
垃
圾
收
集
器
CMS
老
年
代
j
vm
内
存
模
型
jvm
内
存
模
型
jvm
内
存
模
型
– jdk7
OOM
种
类
1. java.lang.OutOfMemoryError
: Java heap space
2. java.lang.OutOfMemoryError
: Java perm space
3. Stack oom
:
stack
深
度
:
Linux-64
位
:1Mk
100
万
;
Windows-64
位
320k
32
万
4.
过
多
线
程
oom
:
vm
最
多
能
创
建
多
少
个
线
程
5. java.lang.OutOfMemoryError
:
GC overhead limit
exceeded
Fullgc
的
原
因
•
system.gc
•
jmap
-
histo:live (
线
上
慎
用
)
•
jvisualvm
操
作
gc
•
Perm
空
间
满
•
Cms gc
:
1. Concurrent mode failed
:
由
于
CMS
回
收
年
老
代
的
速
度
太
慢
2. Prommotion failed:
在
进
行
Minor GC
时
,
survivor space
放
不
下
、
对
象
只
能
放
入
旧
生
代
,
而
此
时
旧
生
代
也
放
不
下
造
成
的
Case 1
Case 1
Case 1
Case 1
Case 1
Case 1
Case1
原
因
1. Old
代
碎
片
,
阀
值
高
,
background gc
没
有
执
行
。
2.
Eden
,
survivor space
满
,
大
对
象
放
不
下
。
类
似
:
Prommotion
failed:
在
进
行
Minor GC
时
,
survivor space
放
不
下
、
对
象
只
能
放
入
旧
生
代
,
而
此
时
旧
生
代
也
放
不
下
造
成
的
Case 1
oom
流
程
Eden
分
配
Old
分
配
ygc
fgc
Soft reference
OOM
失
败
失
败
失
败
失
败
失
败
Case 1
对
象
分
配
流
程
Case 2 -
堆
外
内
存
•
JDK/JVM
里
DirectByteBuffer
•
Netty
DirectByteBuf
/ HeapByteBuf
•
默
认
的
堆
外
内
存
的
大
小
: -Xmx
的
值
里
除
去
一
个
survivor
的
大
小
Case2 Fullgc
堆
内
vs
堆
外
实
验
结
果
---
堆
外
缓
存
没
有
fullgc
*
ConcurrentMap
Guava
TTC
32166ms/32s
47520
ms/47s
Minor C/T
31/1.522
29/1
.312
Full C/T
24/23.212
36/41
.751
MapDB
Ehcache
TTC
40272ms/40s
30814ms/31s
Minor C/T
511/0.557
297/0.430
Full C/T
0/0.000
0/0.000
LocalRedis
NetworkRedis
TTC
176382ms/176s
1h+
Minor C/T
421/0.415
-
Full C/T
0/0.000
-
备
注
:
- TTC: Total Time Cost
总
共
耗
时
- C/T: Count/Time
次
数
/
耗
时
(seconds)
Case2
•
本
文
是
一
次
线
上
的
FGC(Full Garbage Collection)
分
析
及
原
理
剖
析
。
通
过
本
文
,
可
以
深
入
的
了
解
FGC
,
堆
外
Buffer
和
bufferPool
的
设
计
。
千丝万缕的FGC与BufferPool.docx
Case 2
Case 2
并
行
的
Full GC
并
行
Full
GC
也
通
样
会
做
YGC
和
CMS
GC
,
但
是
效
率
高
就
搞
在
CMS
GC
是
走
的
background
的
,
整
个
暂
停
的
过
程
主
要
是
YGC+CMS_initMark+CMS_remark
几
个
阶
段
正
常
的
Full GC
正
常
的
Full GC
其
实
是
整
个
gc
过
程
包
括
ygc
和
cms gc(
这
里
说
的
是
真
正
意
义
上
的
Full GC
,
还
有
些
场
景
虽
然
调
用
Full GC
的
接
口
,
但
是
并
不
会
都
做
,
有
些
时
候
只
做
ygc
,
有
些
时
候
只
做
cms gc)
都
是
由
VMThread
来
执
行
的
,
因
此
整
个
时
间
是
ygc+cms gc
的
时
间
之
和
,
其
中
CMS GC
是
上
面
提
到
的
foreground
式
的
,
因
此
整
个
过
程
会
比
较
长
,
也
是
我
们
要
避
免
的
Foreground gc:
触
发
一
次
cms gc
,
这
个
过
程
就
必
须
是
要
等
内
存
分
配
到
了
线
程
才
能
继
续
往
下
面
走
的
,
因
此
整
个
过
程
必
须
是
STW
的
,
因
此
CMS GC
整
个
过
程
都
是
暂
停
应
用
的
.
整
个
过
程
业
务
线
程
都
是
不
可
用
的
,
效
率
会
影
响
挺
大
。
[
退
化
成
串
行
gc]
Background gc
:
background
顾
名
思
义
是
在
后
台
做
的
,
也
就
是
可
以
不
影
响
正
常
的
业
务
线
程
跑
,
触
发
条
件
比
如
说
old
的
内
存
占
比
超
过
多
少
的
时
候
就
可
能
触
发
一
次
background
式
的
cms gc
,
这
个
过
程
会
经
历
CMS GC
的
所
有
阶
段
。